package Bank;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.swing.JOptionPane;

public class GUI {

	/**
	 * @param args
	 */
	
	static Cliente sessaoCliente;
	static Atendimento currentAtendimento;

	static DB database;
	static boolean encerraAtendimento = false;
	
	public static void main(String[] args) throws ParseException {
		database = new DB(); // Cria objeto inicializando o Banco de Dados		
		inicializaBanco();
		return;
	}
	
	static void inicializaBanco() {
		
		int intOpcaoTipoAtendimento = 0;
		encerraAtendimento = false;
		
		do {
			
			String strOpcaoTipoAtendimento = JOptionPane.showInputDialog(null, 
				"Qual o tipo de atendimento?\n" +
				"\n        1 - Funcionário" +
				"\n        2 - Cliente" +
				"\n        3 - EXIT",
				"Banco Acadêmico",
				JOptionPane.INFORMATION_MESSAGE);	
			
			if (strOpcaoTipoAtendimento == null) {
				return;
			}else if (!strOpcaoTipoAtendimento.equals("")) {
				intOpcaoTipoAtendimento = Integer.parseInt(strOpcaoTipoAtendimento);
			
				if (intOpcaoTipoAtendimento != 1 && intOpcaoTipoAtendimento != 2 && intOpcaoTipoAtendimento != 3)
					JOptionPane.showMessageDialog(null, "Escolha apenas 1 ou 2!", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
			} else {
				JOptionPane.showMessageDialog(null, "Escolha um Opçãoo!", "Entrada Inválida", JOptionPane.INFORMATION_MESSAGE);
			}
		
		} while(intOpcaoTipoAtendimento != 1 && intOpcaoTipoAtendimento != 2 && intOpcaoTipoAtendimento != 3);
		
		switch (intOpcaoTipoAtendimento) {
			case 1:
				currentAtendimento = new Atendimento(TipoAtendimento.AGENCIA);
				atendimentoViaAgencia();
				break;			
			case 2:
				currentAtendimento = new Atendimento(TipoAtendimento.ATM);				
				atendimentoViaCaixaEletronico();
				break;
			case 3:				
				break;
			default:
				break;
		}
		
	}
	
	static void atendimentoViaAgencia() {
		
		if (loginFuncionario()) {
			while (!encerraAtendimento){
				menuFuncionario();
			}
		}	
		
		// Volta para a tela inicial após finalizar um atendimento
		inicializaBanco();
	}
	
	static void atendimentoViaCaixaEletronico(){
		
		if (loginCliente()) {
			while (!encerraAtendimento){
				menuCliente();
			}
		}

		// Volta para a tela inicial após finalizar um atendimento
		inicializaBanco();
	}
		

	static boolean loginFuncionario() {
		
		String login = JOptionPane.showInputDialog(null, 
				"Entre com o Usuário: ",
				"Banco Acadêmico",
				JOptionPane.INFORMATION_MESSAGE);
		if(!(login == null)) {				
			String senha = JOptionPane.showInputDialog(null, 
					"Entre com a senha: ",
					"Banco Acadêmico",
					JOptionPane.INFORMATION_MESSAGE);
			if (!(senha == null)) {					
				for (int i = 0; i < database.listaFuncionariosBanco.size(); i++) {
					if (database.listaFuncionariosBanco.get(i).getUsuario().equals(login) 
							&& database.listaFuncionariosBanco.get(i).getSenha().equals(senha)) {					
						JOptionPane.showMessageDialog(null, "Login Efetuado com Sucesso!", "OK",
								JOptionPane.INFORMATION_MESSAGE);				
						return true;
					}					
				}
				JOptionPane.showMessageDialog(null, "Autenticação Inválida!", "Erro",
						JOptionPane.INFORMATION_MESSAGE);
			}		
		}
		return false;
	}
	
	static boolean loginCliente() {
		if (database.listaClientesBanco.isEmpty()) {
			JOptionPane.showMessageDialog(null, "Nenhum Cliente Cadastrado", "Atenção!",
					JOptionPane.INFORMATION_MESSAGE);
			return false;
		}else {
			
			String numConta = JOptionPane.showInputDialog(null, 
					"Entre com o numero da Conta Corrente: ",
					"Banco Acadêmico",
					JOptionPane.INFORMATION_MESSAGE);
			if(!(numConta == null)) {
				String numAgencia = JOptionPane.showInputDialog(null, 
						"Entre com o Número da agência: ",
						"Banco Acadêmico",
						JOptionPane.INFORMATION_MESSAGE);
				if(!(numAgencia == null)) {
					String senha = JOptionPane.showInputDialog(null, 
							"Entre com a senha: ",
							"Banco Acadêmico",
							JOptionPane.INFORMATION_MESSAGE);
					if(!(senha == null)) {
						if (!(numConta.isEmpty() || numAgencia.isEmpty() || senha.isEmpty())) {
							
							try {
									for (int i = 0; i < database.listaClientesBanco.size(); i++) {
										if(database.listaClientesBanco.get(i).getConta().getNumeroConta() == Integer.valueOf(numConta) &&
												database.listaClientesBanco.get(i).getConta().getAgencia().getNumero() == Integer.valueOf(numAgencia) &&
														database.listaClientesBanco.get(i).getSenha().equals(senha)) {
											
											sessaoCliente = database.listaClientesBanco.get(i);
											
											JOptionPane.showMessageDialog(null, 
													"Bem-Vindo, " + sessaoCliente.getNome(
															) + " " + 
													sessaoCliente.getSobrenome(), 
													"Login Efetuado com Sucesso!",
													JOptionPane.INFORMATION_MESSAGE);									 
											return true;
										}					
									}
								
							} catch(NumberFormatException Error) {							
							
							}
						}
						JOptionPane.showMessageDialog(null, "Autenticação Inválida!", "Erro",
								JOptionPane.INFORMATION_MESSAGE);
					}
				}
			}
			return false;
		}
	}

	
	static void menuFuncionario (){
		
		int intOpcaoTipoAtendimento = 0;
		do {
			
			String strOpcaoTipoAtendimento = JOptionPane.showInputDialog(null, 
				"Escolha a Opçãoo: \n" +
				"\n      1 - Cadastrar nova Conta" +
				"\n      2 - Imprimir saldo" +
				"\n      3 - Extrato" +
				"\n      4 - Depósito" +
				"\n      5 - Saque" +
				"\n      6 - Transferencia" +
				"\n      7 - Logout\n",			
				"Banco Acadêmico",
				JOptionPane.INFORMATION_MESSAGE);
			if(strOpcaoTipoAtendimento == null) {
				intOpcaoTipoAtendimento = 7;
			}else {
				if(!strOpcaoTipoAtendimento.equals("")) {
					intOpcaoTipoAtendimento = Integer.parseInt(strOpcaoTipoAtendimento);
				
					if (intOpcaoTipoAtendimento < 1 || intOpcaoTipoAtendimento > 8)
						JOptionPane.showMessageDialog(null, "Escolha uma Opçãoo válida!", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
				}else {
					JOptionPane.showMessageDialog(null, "Escolha uma das opções!", "Entrada Inválida", JOptionPane.INFORMATION_MESSAGE);
				}
			}
		}while(intOpcaoTipoAtendimento < 1 || intOpcaoTipoAtendimento > 8);
		
		switch (intOpcaoTipoAtendimento) {
		case 1:
			cadastraNovaConta();
			break;
		case 2:
			imprimeSaldo();
			break;
		case 3:
			try {
				imprimeExtrato();
			} catch (ParseException e) {
				e.printStackTrace();
			}
			break;
		case 4:
			efetuaDeposito();
			break;
		case 5:
			efetuaSaque();
			break;
		case 6:
			efetuaTransferencia();
			break;
		case 7:
			logout();
			break;
		default:
			break;
		}
	}
	
	static void menuCliente() {
		
		int intOpcaoTipoAtendimento = 0;
		do {
			
			String strOpcaoTipoAtendimento = JOptionPane.showInputDialog(null, 
				"Escolha a Opçãoo: \n" +
				"\n      1 - Imprimir saldo" +
				"\n      2 - Extrato" +
				"\n      3 - Depósito" +
				"\n      4 - Saque" +
				"\n      5 - Transferencia" +
				"\n      6 - Logout\n",
				"Banco Acadêmico - Bem-Vindo " + sessaoCliente.getNome(),
				JOptionPane.INFORMATION_MESSAGE);
			if(strOpcaoTipoAtendimento == null) {
				intOpcaoTipoAtendimento = 6;
			}else {
				if(!strOpcaoTipoAtendimento.equals("")) {
					intOpcaoTipoAtendimento = Integer.parseInt(strOpcaoTipoAtendimento);
				
					if (intOpcaoTipoAtendimento < 1 || intOpcaoTipoAtendimento > 6)
						JOptionPane.showMessageDialog(null, "Escolha uma Opçãoo válida!", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
				}else {
//					JOptionPane.showMessageDialog(null, "Escolha uma das opções!", "Entrada Inválida", JOptionPane.INFORMATION_MESSAGE);
			}
			}
		}while(intOpcaoTipoAtendimento < 1 || intOpcaoTipoAtendimento > 6);
		
		switch (intOpcaoTipoAtendimento) {
		case 1:
			imprimeSaldo();
			break;
		case 2:
			try {
				imprimeExtrato();
			} catch (ParseException e) {
				e.printStackTrace();
			}
			break;
		case 3:
			efetuaDeposito();
			break;
		case 4:
			efetuaSaque();
			break;
		case 5:
			efetuaTransferencia();
			break;
		case 6:
			logout();
			break;
		default:
			break;
		}
		
	}
	
	static void imprimeSaldo() {
		
		if(currentAtendimento.getTipo().equals(TipoAtendimento.ATM)) {
			JOptionPane.showMessageDialog(null,
					"Seu saldo atual é de R$" + sessaoCliente.getConta().getSaldo() + "0 \n" +
					"Data: " + new Date(),
					"Saldo",
					JOptionPane.INFORMATION_MESSAGE);
		}else {
			
			String strContaCorrente;
			int intContaCorrente = -1;
			do {				
				
				do {			
					strContaCorrente = JOptionPane.showInputDialog(null, 
							"Digite o Número da Conta Corrente: \n",
							"Banco Acadêmico",
							JOptionPane.INFORMATION_MESSAGE);
					if (strContaCorrente == null) {
						return;
					} else if (!strContaCorrente.isEmpty()) {
						try {
							intContaCorrente = Integer.parseInt(strContaCorrente);
						}catch(NumberFormatException Error) {
							
						}
					}else {
						JOptionPane.showMessageDialog(null, 
								"Você deve preencher com o Número da Conta Corrente!",
								"Entrada Inválida",
								JOptionPane.INFORMATION_MESSAGE);
					}
				}while(strContaCorrente.isEmpty());
				
				if(!database.existeContaCorrente(intContaCorrente)) {
					JOptionPane.showMessageDialog(null,
							"Conta Corrente NãO encontrada!" + "\n",
							"Erro!",
							JOptionPane.INFORMATION_MESSAGE);
				}
			}while(!database.existeContaCorrente(intContaCorrente));
			
			JOptionPane.showMessageDialog(null,
					"O saldo do cliente é de R$ " + database.buscaContaCorrente(intContaCorrente).getSaldo() + "0 \n" +
					"Data: " + new Date(),
					"Saldo",
					JOptionPane.INFORMATION_MESSAGE);
		}
		
	}
	
	static void efetuaDeposito() {
		String strValorDeposito, strIdEnvelope, strAgencia, strConta;
		int agencia = -1;
		int conta = -1;
		int idEnvelope = 0;
		Double valorDeposito = 0.0;
		boolean erroValidacao = false;
		ContaCorrente contaCliente = null;
		
		if (currentAtendimento.getTipo().equals(TipoAtendimento.ATM)){
			do {
				try {
					strValorDeposito = JOptionPane.showInputDialog(null, 
						"Digite o valor: \n",
						"Banco Acadêmico",
						JOptionPane.INFORMATION_MESSAGE);
					if(strValorDeposito == null) {
						return;
					}else {
						if (strValorDeposito.isEmpty()) {
							JOptionPane.showMessageDialog(null, 
									"Todos os campos são de preenchimentos obrigatórios!\n" +
									"Tente Novamente!",
									"Erro",
									JOptionPane.INFORMATION_MESSAGE);
							erroValidacao = true;							
						}else {
							valorDeposito = Double.parseDouble(strValorDeposito);
							
							strIdEnvelope = JOptionPane.showInputDialog(null, 
									"Digite o número do envelope: \n",
									"Banco Acadêmico",
									JOptionPane.INFORMATION_MESSAGE);
							if(strIdEnvelope == null) {
								return;
							}else {
								if(strIdEnvelope.isEmpty()) {
									JOptionPane.showMessageDialog(null, 
											"Todos os campos são de preenchimentos obrigatórios!\n" +
											"Tente Novamente!",
											"Erro",
											JOptionPane.INFORMATION_MESSAGE);
									erroValidacao = true;
								}else {
									idEnvelope = Integer.parseInt(strIdEnvelope);
									erroValidacao = false;
								}
							}
							
						}
						
					}		
				}catch (NumberFormatException Erro) {
					JOptionPane.showMessageDialog(null, 
							"Preencha com valores válidos!",
							"Erro",
							JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}
					
			} while (erroValidacao);	
	
			// Cria Deposito e adiciona à lista de depositos do DB
			Deposito deposito = new Deposito(idEnvelope, new Date(), 
					sessaoCliente.getConta().getAgencia(), 
					sessaoCliente.getConta(),
					valorDeposito);
			sessaoCliente.getConta().addDeposito(deposito);
			
			// Adiciona valor na conta do Cliente
			sessaoCliente.getConta().setSaldo(sessaoCliente.getConta().getSaldo() + valorDeposito);
			JOptionPane.showMessageDialog(null, 
					"Depósito efetuado com Sucesso!\n",
					"OK",
					JOptionPane.INFORMATION_MESSAGE);
			
		}
		// Se não for Cliente, então é Funcionário
		else {
			erroValidacao = true;
			do {
				try {
					strAgencia = JOptionPane.showInputDialog(null, 
							"Digite a agência: \n",
							"Banco Acadêmico",
							JOptionPane.INFORMATION_MESSAGE);
					if(strAgencia == null) {
						return;
					}else {
						if (strAgencia.isEmpty()){
							JOptionPane.showMessageDialog(null, 
									"Todos os campos são de preenchimentos obrigatórios!\n" +
									"Tente Novamente!",
									"Erro",
									JOptionPane.INFORMATION_MESSAGE);
							erroValidacao = true;
						} else {
							agencia = Integer.parseInt(strAgencia);							
							strConta = JOptionPane.showInputDialog(null, 
									"Digite a conta: \n",
									"Banco Acadêmico",
									JOptionPane.INFORMATION_MESSAGE);
							if(strConta == null) {
								return;
							}else {
								if (strConta.isEmpty()){
									JOptionPane.showMessageDialog(null, 
											"Todos os campos são de preenchimentos obrigatórios!\n" +
											"Tente Novamente!",
											"Erro",
											JOptionPane.INFORMATION_MESSAGE);
									erroValidacao = true;						
								}else {
									conta = Integer.parseInt(strConta);
									
									strValorDeposito = JOptionPane.showInputDialog(null, 
											"Digite o valor: \n",
											"Banco Acadêmico",
											JOptionPane.INFORMATION_MESSAGE);
									if(strValorDeposito == null) {
										return;
									}else {
										if (strValorDeposito.isEmpty()){
											JOptionPane.showMessageDialog(null, 
													"Todos os campos são de preenchimentos obrigatórios!\n" +
													"Tente Novamente!",
													"Erro",
													JOptionPane.INFORMATION_MESSAGE);
											erroValidacao = true;
										}else {
											valorDeposito = Double.parseDouble(strValorDeposito);
											
											strIdEnvelope = JOptionPane.showInputDialog(null, 
													"Digite o número do envelope: \n",
													"Banco Acadêmico",
													JOptionPane.INFORMATION_MESSAGE);
											if(strIdEnvelope == null) {
												return;
											}else {
												if (strIdEnvelope.isEmpty()){
													JOptionPane.showMessageDialog(null, 
															"Todos os campos são de preenchimentos obrigatórios!\n" +
															"Tente Novamente!",
															"Erro",
															JOptionPane.INFORMATION_MESSAGE);
													erroValidacao = true;
												}else {
													idEnvelope = Integer.parseInt(strIdEnvelope);
													erroValidacao = false;
												}
											}
										}
									}									
								}								
							}		
						}
					}
				}catch(NumberFormatException Erro) {
					JOptionPane.showMessageDialog(null, 
							"Preencha com valores válidos!",
							"Erro",
							JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}
			} while (erroValidacao);				
				
			// Busca a Conta do Cliente
			contaCliente = database.getContaByRef(agencia, conta);
			
			// Cria Deposito e adiciona à lista de depositos do Cliente
			Deposito deposito = new Deposito(idEnvelope, new Date(), 
					contaCliente.getAgencia(), 
					contaCliente,
					valorDeposito);
			contaCliente.addDeposito(deposito);
			
			// Adiciona valor na conta do Cliente
			contaCliente.setSaldo(contaCliente.getSaldo() + valorDeposito);		
			JOptionPane.showMessageDialog(null, 
					"Depósito efetuado com Sucesso!\n",
					"OK",
					JOptionPane.INFORMATION_MESSAGE);
		}		
	}

	static void efetuaSaque() {
		String strValorSaque, strAgencia, strConta;
		int agencia = 0;
		int conta = 0;
		Double valorSaque = 0.0;
		boolean erroValidacao = false;
		
		if (currentAtendimento.getTipo().equals(TipoAtendimento.ATM)){
			do {
				try {
					strValorSaque = JOptionPane.showInputDialog(null, 
						"Digite o valor: \n",
						"Banco Acadêmico",
						JOptionPane.INFORMATION_MESSAGE);
					if(strValorSaque == null) {
						return;
					}else {			
						if (strValorSaque.isEmpty()){
							JOptionPane.showMessageDialog(null, "Você deve preencher um valor para efetuar o Saque.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
							erroValidacao = true;
						}else {
							valorSaque = Double.parseDouble(strValorSaque);							
							// Verifica se existe saldo na Conta do Cliente
							if (sessaoCliente.getConta().getSaldo() < valorSaque){
								JOptionPane.showMessageDialog(null, 
										"O valor para saque deve ser menor do que o seu saldo\n" +
										"Saldo atual: R$ " + sessaoCliente.getConta().getSaldo() + "0\n", 
										"Entrada Inválida",
										JOptionPane.INFORMATION_MESSAGE);
								erroValidacao = true;						
							}else {
								erroValidacao = false;
							}
						}
					}
				}catch(NumberFormatException Erro) {
					JOptionPane.showMessageDialog(null, 
							"Entre com um valor válido!",
							"Erro",
							JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}
			} while (erroValidacao);	
	
			// Cria Saque e adiciona à lista de saques do Cliente
			Saque saque = new Saque(new Date(), 
					sessaoCliente.getConta().getAgencia(), 
					sessaoCliente.getConta(),
					valorSaque);
			sessaoCliente.getConta().addSaque(saque);
			
			// Retira valor da conta do Cliente
			sessaoCliente.getConta().setSaldo(sessaoCliente.getConta().getSaldo() - valorSaque);
			
			// Imprime Saldo e Comprovante
			JOptionPane.showMessageDialog(null, "Saldo atual: R$" + sessaoCliente.getConta().getSaldo(), "Banco Acadêmico",JOptionPane.INFORMATION_MESSAGE);
			JOptionPane.showMessageDialog(null, "--- Comprovante de Saque --- \n" +
												"	Agência: " + sessaoCliente.getConta().getAgencia().getNumero() + "\n" + 
												"	Conta: " + sessaoCliente.getConta().getNumeroConta() + "\n" +
												"	Valor do Saque Efetuado: R$" + valorSaque + "\n" +														
												"--- Comprovante de Saque ---", "Banco Acadêmico",JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		// Se não for Cliente, então é Funcionário
		else {
			do {
				try {
					strAgencia = JOptionPane.showInputDialog(null, 
							"Digite a Agencia: \n",
							"Banco Acadêmico",
							JOptionPane.INFORMATION_MESSAGE);
					if(strAgencia == null) {
						return;
					}else {
						if (strAgencia.isEmpty()){
							JOptionPane.showMessageDialog(null, 
									"Todos os campos são de preenchimentos obrigatórios!\n" +
									"Tente Novamente!",
									"Erro",
									JOptionPane.INFORMATION_MESSAGE);
							erroValidacao = true;
						}else {
							agencia = Integer.parseInt(strAgencia);
							strConta = JOptionPane.showInputDialog(null, 
									"Digite a conta: \n",
									"Banco Acadêmico",
									JOptionPane.INFORMATION_MESSAGE);
							if(strConta == null) {
								return;
							}else {
								if (strConta.isEmpty()){
									JOptionPane.showMessageDialog(null, 
											"Todos os campos são de preenchimentos obrigatórios!\n" +
											"Tente Novamente!",
											"Erro",
											JOptionPane.INFORMATION_MESSAGE);
									erroValidacao = true;
								}else {
									conta = Integer.parseInt(strConta);
									
									strValorSaque = JOptionPane.showInputDialog(null, 
											"Digite o valor: \n",
											"Banco Acadêmico",
											JOptionPane.INFORMATION_MESSAGE);
									if(strValorSaque == null) {
										return;
									}else {
										if (strValorSaque.isEmpty()){
											JOptionPane.showMessageDialog(null, 
													"Todos os campos são de preenchimentos obrigatórios!\n" +
													"Tente Novamente!",
													"Erro",
													JOptionPane.INFORMATION_MESSAGE);
											erroValidacao = true;
										}else {
											valorSaque = Double.parseDouble(strValorSaque);
											erroValidacao = false;
										}											
									}
								}									
							}							
						}						
					}			
				}catch(NumberFormatException Erro) {
					JOptionPane.showMessageDialog(null, 
							"Entre com um valor válido!",
							"Erro",
							JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}
				
				 if(!database.existeContaCorrente(conta)) {
					JOptionPane.showMessageDialog(null, 
							"ContaCorrente não encontrada!\n" +
							"Tente Novamente!",
							"Erro",
							JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}else {
					if(database.buscaContaCorrente(conta).getAgencia().getNumero() == agencia){
						erroValidacao = false;
					}else{
						JOptionPane.showMessageDialog(null, 
								"Conta Corrente não existe nesta agência!\n" +
								"Tente Novamente!",
								"Erro",
								JOptionPane.INFORMATION_MESSAGE);
						erroValidacao = true;
					}
				}
				
			} while (erroValidacao);				
				
			// Verifica se existe saldo na Conta do Cliente
			boolean hasSaldo = false;						
			ContaCorrente contaCliente = database.getContaByRef(agencia, conta);
			if (contaCliente.getSaldo() >= valorSaque){
				hasSaldo = true;
			}				
			
			if (hasSaldo){
					// Se houver saldo suficiente, cria Saque e adiciona à lista de saques do Cliente
					Saque saque = new Saque(new Date(), 
							contaCliente.getAgencia(), 
							contaCliente,
							valorSaque);
					contaCliente.addSaque(saque);
					
					// Retira valor da conta do Cliente
					contaCliente.setSaldo(contaCliente.getSaldo() - valorSaque);
					
					// Imprime Saldo e Comprovante
					JOptionPane.showMessageDialog(null, "Saldo atual: R$" + contaCliente.getSaldo(), "Banco Acadêmico",JOptionPane.INFORMATION_MESSAGE);
					JOptionPane.showMessageDialog(null, "--- Comprovante de Saque --- \n" +
														"	Agência: " + contaCliente.getAgencia().getNumero() + "\n" + 
														"	Conta: " + contaCliente.getNumeroConta() + "\n" +
														"	Valor do Saque Efetuado: R$" + valorSaque + "\n" +														
														"--- Comprovante de Saque ---", "Banco Acadêmico",JOptionPane.INFORMATION_MESSAGE);					
			} 
			else {
					JOptionPane.showMessageDialog(null, "O valor para saque deve ser menor do que o seu saldo", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;					
			}				
		}
		
	}
	
	static void efetuaTransferencia() {
		String strValorTransferencia, strAgenciaOrigem, strContaOrigem, strAgenciaDestino, strContaDestino;
		int agenciaOrigem, contaOrigem, agenciaDestino, contaDestino;
		Double valorTransferencia = 0.0;
		boolean erroValidacao = false;
		
		if (currentAtendimento.getTipo().equals(TipoAtendimento.ATM)){
			do {

				strAgenciaDestino = JOptionPane.showInputDialog(null, 
						"Digite o número da agência destino: \n",
						"Banco Academico",
						JOptionPane.INFORMATION_MESSAGE);
				
				strContaDestino = JOptionPane.showInputDialog(null, 
						"Digite o número da conta destino: \n",
						"Banco Academico",
						JOptionPane.INFORMATION_MESSAGE);
				
				strValorTransferencia = JOptionPane.showInputDialog(null, 
					"Digite o valor: \n",
					"Banco Academico",
					JOptionPane.INFORMATION_MESSAGE);			
			
				if (strAgenciaDestino.isEmpty()){
					JOptionPane.showMessageDialog(null, "Agência inválida ou inexistente.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}
				
				if (strContaDestino.isEmpty()){
					JOptionPane.showMessageDialog(null, "Conta inválida ou inexistente.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}			
				
				if (strValorTransferencia.isEmpty()){
					JOptionPane.showMessageDialog(null, "Você deve preencher um valor para efetuar o Deposito.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}							
					
			} while (erroValidacao);	
	
			boolean hasSaldo = false;
			valorTransferencia = Double.parseDouble(strValorTransferencia);
			agenciaDestino = Integer.parseInt(strAgenciaDestino);
			contaDestino = Integer.parseInt(strContaDestino);
			ContaCorrente contaCorrenteDestino = database.getContaByRef(agenciaDestino, contaDestino); // Busca conta destino pela referência
			
			if (sessaoCliente.getConta().getSaldo() >= valorTransferencia){
				hasSaldo = true;
			}		
			
			// Testa se tem saldo suficiente para efetuar a Transferência
			if (hasSaldo){
				// Cria Transferência na Conta de origem							
				Transferencia transferencia_origem = new Transferencia(new Date(), 
						sessaoCliente.getConta().getAgencia(), sessaoCliente.getConta(),
						contaCorrenteDestino.getAgencia(), contaCorrenteDestino,
						valorTransferencia, TipoTransferencia.DEBITO);
				sessaoCliente.getConta().addTransferencia(transferencia_origem);
				
				// Remove valor da conta do Cliente que originou a transferência
				sessaoCliente.getConta().setSaldo(sessaoCliente.getConta().getSaldo() - valorTransferencia);
				
				// Cria Transferência na Conta de destino
				Transferencia transferencia_destino = new Transferencia(new Date(), 
						sessaoCliente.getConta().getAgencia(), sessaoCliente.getConta(),
						contaCorrenteDestino.getAgencia(), contaCorrenteDestino,
						valorTransferencia, TipoTransferencia.CREDITO);
				contaCorrenteDestino.addTransferencia(transferencia_destino);
				
				// Remove valor da conta do Cliente que originou a transferência
				contaCorrenteDestino.setSaldo(sessaoCliente.getConta().getSaldo() - valorTransferencia);
			}
			else {
				JOptionPane.showMessageDialog(null, "O valor para transferência deve ser menor do que o seu saldo atual", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
				erroValidacao = true;					
			}	
		}
		// Se não for Cliente, então é Funcionário
		else {
			do {

				strAgenciaOrigem = JOptionPane.showInputDialog(null, 
						"Digite o número da agência origem: \n",
						"Banco Academico",
						JOptionPane.INFORMATION_MESSAGE);
				
				strContaOrigem = JOptionPane.showInputDialog(null, 
						"Digite o número da conta origem: \n",
						"Banco Academico",
						JOptionPane.INFORMATION_MESSAGE);
				
				strAgenciaDestino = JOptionPane.showInputDialog(null, 
						"Digite o número da agência destino: \n",
						"Banco Academico",
						JOptionPane.INFORMATION_MESSAGE);
				
				strContaDestino = JOptionPane.showInputDialog(null, 
						"Digite o número da conta destino: \n",
						"Banco Academico",
						JOptionPane.INFORMATION_MESSAGE);				
				
				strValorTransferencia = JOptionPane.showInputDialog(null, 
					"Digite o valor: \n",
					"Banco Academico",
					JOptionPane.INFORMATION_MESSAGE);			
			
				if (strAgenciaOrigem.isEmpty()){
					JOptionPane.showMessageDialog(null, "Agência origem inválida ou inexistente.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}
				
				if (strContaOrigem.isEmpty()){
					JOptionPane.showMessageDialog(null, "Conta origem inválida ou inexistente.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}	
				
				if (strAgenciaDestino.isEmpty()){
					JOptionPane.showMessageDialog(null, "Agência destino inválida ou inexistente.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}
				
				if (strContaDestino.isEmpty()){
					JOptionPane.showMessageDialog(null, "Conta destino inválida ou inexistente.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}				
				
				if (strValorTransferencia.isEmpty()){
					JOptionPane.showMessageDialog(null, "Você deve preencher um valor para efetuar o Deposito.", "Entrada Inválida",JOptionPane.INFORMATION_MESSAGE);
					erroValidacao = true;
				}							
					
			} while (erroValidacao);	
	
			valorTransferencia = Double.parseDouble(strValorTransferencia);
			agenciaOrigem = Integer.parseInt(strAgenciaOrigem);
			contaOrigem = Integer.parseInt(strContaOrigem);
			agenciaDestino = Integer.parseInt(strAgenciaDestino);
			contaDestino = Integer.parseInt(strContaDestino);			
			ContaCorrente contaCorrenteDestino = database.getContaByRef(agenciaDestino, contaDestino); // Busca conta destino pela referência
			ContaCorrente contaCorrenteOrigem = database.getContaByRef(agenciaOrigem, contaOrigem); // Busca conta origem pela referência			
			
			// Cria Transferência na Conta de origem							
			Transferencia transferencia_origem = new Transferencia(new Date(), 
					contaCorrenteOrigem.getAgencia(), contaCorrenteOrigem,
					contaCorrenteDestino.getAgencia(), contaCorrenteDestino,
					valorTransferencia, TipoTransferencia.DEBITO);
			contaCorrenteOrigem.addTransferencia(transferencia_origem);
			
			// Remove valor da conta do Cliente que originou a transferência
			contaCorrenteOrigem.setSaldo(contaCorrenteOrigem.getSaldo() - valorTransferencia);
			
			// Cria Transferência na Conta de destino
			Transferencia transferencia_destino = new Transferencia(new Date(), 
					contaCorrenteOrigem.getAgencia(), contaCorrenteOrigem,
					contaCorrenteDestino.getAgencia(), contaCorrenteDestino,
					valorTransferencia, TipoTransferencia.CREDITO);
			contaCorrenteDestino.addTransferencia(transferencia_destino);
			
			// Adiciona valor na conta do Cliente que deve receber a transferência
			contaCorrenteDestino.setSaldo(contaCorrenteDestino.getSaldo() + valorTransferencia);			
		}
	}
	
	@SuppressWarnings("deprecation")
	static void imprimeExtrato() throws ParseException {		
		TreeMap<Date, String> historico = new TreeMap<Date, String>();
		Entry<Date, String> readEntry;
		int agencia = 0, conta = 0;
		String stringImprimeExtrato = "";
		
		String strAgencia = null;
		String strConta = null;
		if (currentAtendimento.equals(TipoAtendimento.AGENCIA)){
			strAgencia = JOptionPane.showInputDialog(null, 
					"Digite a agência: \n",
					"Banco Academico",
					JOptionPane.INFORMATION_MESSAGE);
			
			strConta = JOptionPane.showInputDialog(null, 
					"Digite a conta: \n",
					"Banco Academico",
					JOptionPane.INFORMATION_MESSAGE);
			
			agencia = Integer.parseInt(strAgencia);
			conta = Integer.parseInt(strConta);
		}
		
		ContaCorrente contaExtrato;
		if (currentAtendimento.equals(TipoAtendimento.AGENCIA)){
			contaExtrato = database.getContaByRef(agencia, conta);
		}
		else {
			contaExtrato = sessaoCliente.getConta();
		}
		
		String strTipoExtrato = JOptionPane.showInputDialog(null, 
				"Digite o tipo de extrato desejado: \n" +
				"1 - Mês Anterior \n" +
				"2 - Inserir Período \n",
				"Banco Academico",
				JOptionPane.INFORMATION_MESSAGE);
		
		int tipoExtrato = 0;
		if (strTipoExtrato.isEmpty()){
			tipoExtrato = 3; 
		}
		else {
			tipoExtrato = Integer.parseInt(strTipoExtrato);	
		}
		
		// Carrega saques na tabela hash
		for (int i = 0; i < contaExtrato.getSaques().size(); i++){
			historico.put(contaExtrato.getSaques().get(i).getData(),
					contaExtrato.getSaques().get(i).getData() + " - Saque - R$" +
							contaExtrato.getSaques().get(i).getValor() + " D \n"
						);
		}
		
		// Carrega depositos na tabela hash
		for (int i = 0; i < contaExtrato.getDepositos().size(); i++){
			historico.put(contaExtrato.getDepositos().get(i).getData(),
					contaExtrato.getDepositos().get(i).getData() + " - Deposito - R$" +
							contaExtrato.getDepositos().get(i).getValor() + " C \n"
						);
		}
		
		// Carrega transferências na tabela hash
		for (int i = 0; i < contaExtrato.getTranferencias().size(); i++){
			historico.put(contaExtrato.getTranferencias().get(i).getData(),
					contaExtrato.getTranferencias().get(i).getData() + " - Transferência - R$" +
							contaExtrato.getTranferencias().get(i).getValor() + " " +
							getCharTransferenciaTipo(contaExtrato.getTranferencias().get(i)) + "\n"
						);
		}
				
		// Define período do extrato
		switch (tipoExtrato){
			case 1:
				int mesesAnteriores = 1;
				String strMesesAnteriores = "";
				do {
					strMesesAnteriores = JOptionPane.showInputDialog(null, 
							"Digite o extrato de quantos meses anteriores você deseja imprimir: (de 1 à 6 meses atrás) \n",
							"Banco Academico",
							JOptionPane.INFORMATION_MESSAGE);
					mesesAnteriores = Integer.parseInt(strMesesAnteriores);
				} while ((strMesesAnteriores.isEmpty()) || (mesesAnteriores < 1) || (mesesAnteriores > 6));				
				
				// Adiciona cabeçalho:
				stringImprimeExtrato += "--- Extrato - Período: Últimos " + (30*mesesAnteriores) + " dias --- \n";
				// Busca data mais recente no historico
				readEntry = historico.lastEntry();
				GregorianCalendar cl = new GregorianCalendar();
				cl.setTime(readEntry.getKey());
				cl.add(Calendar.DAY_OF_MONTH, -30*mesesAnteriores);
				
				// Pega entrada menos recente com relação ao limite
				readEntry = historico.higherEntry(cl.getTime());
				//historico.remove(readEntry.getKey());
				while (!(readEntry == null)){
					historico.remove(readEntry.getKey());					
					stringImprimeExtrato += readEntry.getValue();					
					readEntry = historico.higherEntry(cl.getTime());
				}				
				
			break;
			case 2:
				String strDataInicio = "";
				String strDataFim = "";
				Date dataInicioExtrato, dataFimExtrato;
				
				do {
					strDataInicio = JOptionPane.showInputDialog(null, 
							"Digite a data de início do extrato: (formato ddmmYYYY) \n",
							"Banco Academico",
							JOptionPane.INFORMATION_MESSAGE);
					
					strDataFim = JOptionPane.showInputDialog(null, 
							"Digite a data de início do extrato: (formato ddmmYYYY) \n",
							"Banco Academico",
							JOptionPane.INFORMATION_MESSAGE);
				} while ((strDataInicio.isEmpty()) || strDataFim.isEmpty());
				
				dataInicioExtrato = new SimpleDateFormat("ddMMyyyy").parse(strDataInicio);
				dataFimExtrato = new SimpleDateFormat("ddMMyyyy").parse(strDataFim);
				
				// Adiciona cabeçalho:
				stringImprimeExtrato += "--- Extrato - Período: de " + dataInicioExtrato.getDay() + "/" + dataInicioExtrato.getMonth() + "/" + dataInicioExtrato.getYear()
						+ " até " 
						+ dataFimExtrato.getDay() + "/" + dataFimExtrato.getMonth() + "/" + dataFimExtrato.getYear()
						+ " --- \n";
				
				// Percorre removendo entradas mais antigas que a data de início e mais novas que a data de fim
				readEntry = historico.higherEntry(dataInicioExtrato);
				//historico.remove(readEntry.getKey());
				while (!(readEntry == null)){
					historico.remove(readEntry.getKey());
					if (readEntry.getKey().compareTo(dataFimExtrato) < 0){
						stringImprimeExtrato += readEntry.getValue();
					}
					readEntry = historico.higherEntry(dataInicioExtrato);
				}						
			break;		
		}		
		
		stringImprimeExtrato += "\nSaldo atual: R$" + contaExtrato.getSaldo();
		
		JOptionPane.showMessageDialog(null, stringImprimeExtrato, "Banco Academico",JOptionPane.INFORMATION_MESSAGE);
	}
	
	private static String getCharTransferenciaTipo(Transferencia transferencia) {
		if (transferencia.getTipo().equals(TipoTransferencia.CREDITO)){
			return "C";
		}
		else {
			return "D";
		}
	}

	static void cadastraNovaConta() {		
		
		boolean erroCadastro = true;
		int intDadosCorretos = 0;
		do {
			String nome = null;
			String sobreNome = null;
			String nomeUsuario = null;
			String senha = null;
			String dataNascimento = null;
			String cpf = null;
			String strDadosCorretos = null;
			int numeroConta;
			int intAgenciaEscolhida = -1;
			Double saldo= 0.0;		
			boolean saldoInvalido = true;
			boolean escolheuAgencia = false;
			boolean escolheuSimNao = false;
		
							
			// Criacao Cliente
		
			nome = JOptionPane.showInputDialog(null, 
					"Entre com o Primeiro Nome do cliente a ser cadastrado: ",
					"Banco Acadêmico",
					JOptionPane.INFORMATION_MESSAGE);
			if(!(nome == null)) {
				sobreNome = JOptionPane.showInputDialog(null, 
						"Entre com o Sobrenome do cliente a ser cadastrado: ",
						"Banco Acadêmico",
						JOptionPane.INFORMATION_MESSAGE);
				if(!(sobreNome == null)) {
					dataNascimento = JOptionPane.showInputDialog(null, 
							"Entre com a data de nascimento do cliente a ser cadastrado: ",
							"Banco Acadêmico",
							JOptionPane.INFORMATION_MESSAGE);
					if(!(dataNascimento == null)) {
						cpf = JOptionPane.showInputDialog(null, 
								"Entre com o CPF do cliente a ser cadastrado: ",
								"Banco Acadêmico",
								JOptionPane.INFORMATION_MESSAGE);
						if(!(cpf == null)) {
							nomeUsuario = JOptionPane.showInputDialog(null, 
									"Entre com o nome de usuário a ser utilizado: ",
									"Banco Acadêmico",
									JOptionPane.INFORMATION_MESSAGE);
							if(!(nomeUsuario == null)) {
								senha = JOptionPane.showInputDialog(null, 
										"Entre com a senha para esta conta: ",
										"Banco Acadêmico",
										JOptionPane.INFORMATION_MESSAGE);
								if(!(senha == null)) {

									// Criacao Conta Corrente									
									numeroConta = database.getListaContasBanco().size() + 1;
									//Agencia agencia;
									saldo = 0.0;
									String strAgenciaEscolhida;
									String strListaAgencia = "";
									
									// Cria uma string com o Número da agencia e o nome dela
									for (int i = 0; i < database.listaAgenciasBanco.size() ; i++) {
										strListaAgencia = strListaAgencia + "\n" + database.listaAgenciasBanco.get(i).getNumero() + 
												" - " + database.listaAgenciasBanco.get(i).getNome();
									}
									
									do {
										try {
											strAgenciaEscolhida = JOptionPane.showInputDialog(null, 
																"Escolha uma agencia: \n" + strListaAgencia,					
																"Banco Acadêmico",
																JOptionPane.INFORMATION_MESSAGE);
											if(strAgenciaEscolhida == null) {
												return;										
											}else {
												if(strAgenciaEscolhida.isEmpty()) {
													JOptionPane.showMessageDialog(null, 
															"Escolha uma opção válida!",
															"Erro",
															JOptionPane.INFORMATION_MESSAGE);
												}else {
													intAgenciaEscolhida = Integer.parseInt(strAgenciaEscolhida);
													if(!database.existeAgencia(intAgenciaEscolhida)) {
														JOptionPane.showMessageDialog(null, 
																"Escolha uma opção válida!",
																"Erro",
																JOptionPane.INFORMATION_MESSAGE);
													}else {
														escolheuAgencia = true;
													}
												}											
											}
										}catch (Exception Erro) {
											JOptionPane.showMessageDialog(null, 
													"Escolha uma opção válida!",
													"Erro",
													JOptionPane.INFORMATION_MESSAGE);
										}	
									}while(escolheuAgencia == false);
									
									JOptionPane.showMessageDialog(null, "Número da Conta Corrente: " + numeroConta , "Banco Acadêmico", JOptionPane.INFORMATION_MESSAGE);
									
									do {
										try {
											String strSaldo = JOptionPane.showInputDialog(null, 
													"Entre com o Saldo Inicial: \n",
													"Banco Acadêmico",
													JOptionPane.INFORMATION_MESSAGE);
											if(strSaldo == null) {
												return;
											}else {
												if(strSaldo.isEmpty()) {
													saldoInvalido = false;
												}else {
													saldo = Double.parseDouble(strSaldo);
													saldoInvalido = false;
												}
											}
										}catch (NumberFormatException Error) {
											JOptionPane.showMessageDialog(null, 
													"Entre com um valor válido!",
													"Erro",
													JOptionPane.INFORMATION_MESSAGE);
											saldo = 0.0;
										}
									}while(saldoInvalido);
									
									if (nome.isEmpty() || sobreNome.isEmpty() || dataNascimento.isEmpty() || cpf.isEmpty() || nomeUsuario.isEmpty() || senha.isEmpty()){
										JOptionPane.showMessageDialog(null, 
												"Todos os campos são de preenchimentos obrigatórios!\n" +
												"Tente Novamente!",
												"Erro",
												JOptionPane.INFORMATION_MESSAGE);
										return;
									}
									
									do {
										try {
											strDadosCorretos = JOptionPane.showInputDialog(null, 
													"Os dados estão corretos? \n" +
													"Nome: " + nome + " " + sobreNome + "\n" +
													"CPF: " + cpf + "\n" +
													"Data de Nascimento: " + dataNascimento + "\n" +
													"Usuario: " + nomeUsuario + "\n" +
													"Senha: " + senha + "\n\n" +
													"Dados bancários: \n\n" +
													"Agêcia: " + database.buscaAgencia(intAgenciaEscolhida).getNumero() + " - " + database.buscaAgencia(intAgenciaEscolhida).getNome() + "\n" +
													"Número da Conta Corrente: " + numeroConta + "\n" +
													"Saldo Inicial: R$ " + saldo + "0 \n" +
													"1 - SIM         2 - NÃO",
													"Banco Acadêmico",
													JOptionPane.INFORMATION_MESSAGE);
											
											if(strDadosCorretos == null) {
												return;
											}else {
												if(strDadosCorretos.isEmpty()) {
													JOptionPane.showMessageDialog(null, 
															"Escolha uma das opções!",
															"Erro",
															JOptionPane.INFORMATION_MESSAGE);
												}else {
													intDadosCorretos = Integer.parseInt(strDadosCorretos);
													if(intDadosCorretos != 1 && intDadosCorretos != 2) {
														JOptionPane.showMessageDialog(null, 
																"Entre com um valor válido!",
																"Erro",
																JOptionPane.INFORMATION_MESSAGE);
														escolheuSimNao = false;
													}else {
														if(intDadosCorretos == 2) {
															return;
														}else {
															// Adiciona cliente na lista de clientes do banco
															ContaCorrente novaConta = new ContaCorrente(numeroConta, database.buscaAgencia(intAgenciaEscolhida), saldo);
															database.listaContasBanco.add(novaConta);
															Cliente clienteCadastro = new Cliente(nome, sobreNome, dataNascimento, nomeUsuario, senha, novaConta, cpf);
															database.addClienteToList(clienteCadastro);																
															JOptionPane.showMessageDialog(null, "Cliente cadastrado com Sucesso!", "Banco Acadêmico", JOptionPane.INFORMATION_MESSAGE);
															return;
														}
														
													}
													
												}
												
											}
											
										} catch (NumberFormatException Error) {
											JOptionPane.showMessageDialog(null, 
													"Entre com um valor válido!",
													"Erro",
													JOptionPane.INFORMATION_MESSAGE);
											escolheuSimNao = false;
										}
									}while(!escolheuSimNao);									
									
								} // SENHA = NULL
							}
						}
					}
				}
			}
			if(erroCadastro){
				return;
			}
		}while(erroCadastro);
	}
	
	static void logout(){
		encerraAtendimento = true;
		sessaoCliente = null;
		JOptionPane.showMessageDialog(null, "Atendimento finalizado. Obrigado por utilizar os nossos serviços!", "Banco Acadêmico",JOptionPane.INFORMATION_MESSAGE);
	}	
	
	
	
}
	